using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
using System.ComponentModel.Design;


namespace sforceExplorer
{

	// A delegate type for hooking up change notifications.
	public delegate void FieldDoubleClickedEventHandler(object sender, EventArgs e);
	public delegate void SelectListChangedEventHandler(object sender, ApiBrowserControl.SelectListChangedArguments[] e);
	
	public class ApiBrowserControl : System.Windows.Forms.UserControl
	{
		internal System.Windows.Forms.ImageList ImageList1;
		internal System.Windows.Forms.ContextMenu ContextMenu2;
		internal System.Windows.Forms.MenuItem muAddFieldToCode;
		internal System.Windows.Forms.ContextMenu ContextMenu1;
		internal System.Windows.Forms.MenuItem muCreateTable;
		internal System.Windows.Forms.MenuItem mnuCopy;
		internal System.Windows.Forms.TreeView tvDesc;
		private System.ComponentModel.IContainer components;
		private bool _MultiObjectSelect = false;
		public event FieldDoubleClickedEventHandler FieldDoubleClicked;
		public event SelectListChangedEventHandler SelectListChanged;
		private sforce.DescribeSObjectResult _currentObject;
		private System.Windows.Forms.MenuItem mnuDocObject;
		private System.Windows.Forms.MenuItem mnuDocAllObjects;
		private TreeNode _currentRootNode;
		
		public class SelectListChangedArguments 
		{
			private string _TableName;
			private ArrayList _SelectedFields;
			
			public SelectListChangedArguments(string tableName, string[] selectedFields) 
			{
				TableName = tableName;
				SelectedFields = selectedFields;
			}

			public void AddField(string field) 
			{
				if (_SelectedFields == null) _SelectedFields = new ArrayList();
				_SelectedFields.Add(field);
			}

			public SelectListChangedArguments() 
			{
			}

			public string TableName
			{
				get { return _TableName; }
				set {_TableName = value; }
			}
			public string[] SelectedFields
			{
				get  { return (string[])_SelectedFields.ToArray(typeof(string)); }
				set 
				{ 
					_SelectedFields = new ArrayList(value.Length);
					for (int i=0;i<value.Length;i++) 
						_SelectedFields.Add(value[i]);
				}
			}
		}

		public ApiBrowserControl()
		{
			InitializeComponent();

			tvDesc.AfterCheck +=new TreeViewEventHandler(tvDesc_AfterCheck);
			tvDesc.BeforeSelect +=new TreeViewCancelEventHandler(tvDesc_BeforeSelect);
			tvDesc.MouseDown += new MouseEventHandler(tvDesc_MouseDown);
		}

		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if(components != null)
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		#region Component Designer generated code
		/// <summary> 
		/// Required method for Designer support - do not modify 
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			this.components = new System.ComponentModel.Container();
			System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(ApiBrowserControl));
			this.ImageList1 = new System.Windows.Forms.ImageList(this.components);
			this.ContextMenu2 = new System.Windows.Forms.ContextMenu();
			this.muAddFieldToCode = new System.Windows.Forms.MenuItem();
			this.ContextMenu1 = new System.Windows.Forms.ContextMenu();
			this.muCreateTable = new System.Windows.Forms.MenuItem();
			this.mnuCopy = new System.Windows.Forms.MenuItem();
			this.mnuDocObject = new System.Windows.Forms.MenuItem();
			this.mnuDocAllObjects = new System.Windows.Forms.MenuItem();
			this.tvDesc = new System.Windows.Forms.TreeView();
			this.SuspendLayout();
			// 
			// ImageList1
			// 
			this.ImageList1.ColorDepth = System.Windows.Forms.ColorDepth.Depth32Bit;
			this.ImageList1.ImageSize = new System.Drawing.Size(16, 16);
			this.ImageList1.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("ImageList1.ImageStream")));
			this.ImageList1.TransparentColor = System.Drawing.Color.Transparent;
			// 
			// ContextMenu2
			// 
			this.ContextMenu2.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
																						 this.muAddFieldToCode});
			// 
			// muAddFieldToCode
			// 
			this.muAddFieldToCode.Index = 0;
			this.muAddFieldToCode.Text = "Copy Field Name";
			// 
			// ContextMenu1
			// 
			this.ContextMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
																						 this.muCreateTable,
																						 this.mnuCopy,
																						 this.mnuDocObject,
																						 this.mnuDocAllObjects});
			this.ContextMenu1.Popup += new System.EventHandler(this.ContextMenu1_Popup);
			// 
			// muCreateTable
			// 
			this.muCreateTable.Index = 0;
			this.muCreateTable.Text = "Create Simple Schema Definition";
			this.muCreateTable.Click += new System.EventHandler(this.muCreateTable_Click);
			// 
			// mnuCopy
			// 
			this.mnuCopy.Index = 1;
			this.mnuCopy.Text = "Copy Entity Name";
			// 
			// mnuDocObject
			// 
			this.mnuDocObject.Index = 2;
			this.mnuDocObject.Text = "Document Object";
			this.mnuDocObject.Click += new System.EventHandler(this.mnuDocObject_Click);
			// 
			// mnuDocAllObjects
			// 
			this.mnuDocAllObjects.Index = 3;
			this.mnuDocAllObjects.Text = "Document All Objects";
			// 
			// tvDesc
			// 
			this.tvDesc.AllowDrop = true;
			this.tvDesc.CheckBoxes = true;
			this.tvDesc.Dock = System.Windows.Forms.DockStyle.Fill;
			this.tvDesc.Font = new System.Drawing.Font("Verdana", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
			this.tvDesc.HideSelection = false;
			this.tvDesc.HotTracking = true;
			this.tvDesc.ImageList = this.ImageList1;
			this.tvDesc.ItemHeight = 18;
			this.tvDesc.Location = new System.Drawing.Point(0, 0);
			this.tvDesc.Name = "tvDesc";
			this.tvDesc.SelectedImageIndex = 1;
			this.tvDesc.Size = new System.Drawing.Size(248, 328);
			this.tvDesc.Sorted = true;
			this.tvDesc.TabIndex = 12;
			this.tvDesc.DoubleClick += new System.EventHandler(this.tvDesc_DoubleClick);
			this.tvDesc.BeforeCheck += new System.Windows.Forms.TreeViewCancelEventHandler(this.tvDesc_BeforeCheck);
			// 
			// ApiBrowserControl
			// 
			this.ContextMenu = this.ContextMenu1;
			this.Controls.Add(this.tvDesc);
			this.Name = "ApiBrowserControl";
			this.Size = new System.Drawing.Size(248, 328);
			this.ResumeLayout(false);

		}
		#endregion

		[Category("Browser Specific"), Description("Enable selecting multiple objects")]
		public bool MultiObjectSelect
		{
			get
			{
				return _MultiObjectSelect;
			}
			set
			{
				_MultiObjectSelect = value;
			}
		}
	

		public void Describe(bool clearCache) 
		{
			sforceExplorer.sforce.DescribeGlobalSObjectResult [] ret;
			
			this.tvDesc.Nodes.Clear();
			try 
			{	if (clearCache)
					DataCache.Cache.Clear();

				ret = (sforceExplorer.sforce.DescribeGlobalSObjectResult[])Utility.GetObjectTypes().ToArray(typeof(sforceExplorer.sforce.DescribeGlobalSObjectResult));
			}
			catch (Exception ex) 
			{
				System.Windows.Forms.MessageBox.Show("Unexpected error calling describe: " + ex.Message);
				return;
			}

			int i;

			System.Windows.Forms.TreeNode newNode;
			for (i = 0; i < ret.Length; i++)
			{
				newNode = tvDesc.Nodes.Add(ret[i].name);
				newNode.NodeFont = new System.Drawing.Font("Verdana", 8, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
				newNode.ImageIndex = 13;
				newNode.SelectedImageIndex = 13;
				newNode.Nodes.Add("holder");
				//newNode.Tag = "root";
				newNode.Collapse();
			}
			this.tvDesc.BeforeExpand += new TreeViewCancelEventHandler(tvDesc_BeforeExpand);
		}
		
		private void ExpandRootNode(System.Windows.Forms.TreeNode rootNode)
		{
			if (rootNode.Nodes.Count == 0 && rootNode.Parent == null) 
			{
				this.Cursor = Cursors.WaitCursor;
				AddEntityToTree(rootNode);
				rootNode.Expand();
				this.Cursor = Cursors.Default;
			}
		}
		

		private void RemoveCheckBox(System.Windows.Forms.TreeNode n) 
		{
			TreeViewExtender.RemoveCheckBoxFromNode(n);
		}
		private void RemoveImage(System.Windows.Forms.TreeNode n) 
		{
			TreeViewExtender.RemoveImageFromNode(n);
		}
		private void AddEntityToTree(System.Windows.Forms.TreeNode RootNode)
		{
			string EntityName = RootNode.Text;
			this.FindForm().Cursor = Cursors.WaitCursor;
			sforce.DescribeSObjectResult ret;
			RootNode.Nodes.Clear();

			try 
			{
				ret = Utility.binding.describeSObject(EntityName);
				RootNode.Tag = ret;
				
				//Add the access node for the entity
				System.Windows.Forms.TreeNode aNode = RootNode.Nodes.Add("Access");
				aNode.SelectedImageIndex = 4;
				aNode.ImageIndex = 4;
				aNode.Tag = "access";
				RemoveCheckBox(aNode);

				this.AddAccessToTree(aNode, ret, 6);

				if (ret.keyPrefix != null) 
				{
					System.Windows.Forms.TreeNode kpNode = RootNode.Nodes.Add("  Id Prefix - " + ret.keyPrefix);
					kpNode.ImageIndex = 30;
					kpNode.SelectedImageIndex = 30;
					RemoveCheckBox(kpNode);
				}

				if (ret.urlDetail != null) 
				{
					System.Windows.Forms.TreeNode urlNode = RootNode.Nodes.Add(" URL - Detail");
					urlNode.ImageIndex = 29;
					urlNode.SelectedImageIndex = 29;
					System.Windows.Forms.TreeNode url = urlNode.Nodes.Add(ret.urlDetail);
					RemoveCheckBox(url);
					RemoveImage(url);
					RemoveCheckBox(urlNode);
				}

				if (ret.urlEdit != null) 
				{
					System.Windows.Forms.TreeNode urlNode = RootNode.Nodes.Add(" URL - Edit");
					urlNode.ImageIndex = 29;
					urlNode.SelectedImageIndex = 29;
					System.Windows.Forms.TreeNode url = urlNode.Nodes.Add(ret.urlEdit);
					RemoveCheckBox(url);
					RemoveImage(url);
					RemoveCheckBox(urlNode);
				}

				if (ret.urlNew != null) 
				{
					System.Windows.Forms.TreeNode urlNode = RootNode.Nodes.Add(" URL - New");
					urlNode.ImageIndex = 29;
					urlNode.SelectedImageIndex = 29;
					System.Windows.Forms.TreeNode url = urlNode.Nodes.Add(ret.urlNew);
					RemoveCheckBox(url);
					RemoveImage(url);
					RemoveCheckBox(urlNode);
				}
				
				//Add the fields to the tree
				System.Windows.Forms.TreeNode fNode = RootNode.Nodes.Add("Fields");
				fNode.ImageIndex = 5;
				fNode.SelectedImageIndex = 5;
				fNode.Tag = "fields";
				AddFieldsToTree(fNode, ret.fields, 0);
			}
			catch (Exception ex) 
			{
				System.Windows.Forms.MessageBox.Show("Unexpected error: " + ex.Message);
			}
			this.FindForm().Cursor = Cursors.Default;

		}
		
		private void AddFieldsToTree(System.Windows.Forms.TreeNode fieldsNode, sforce.Field[] fields, int IconIndex)
		{
			for (int i=0;i<fields.Length;i++)
			{
				try 
				{
					sforce.Field field = fields[i];
					System.Windows.Forms.TreeNode fNode;
					if (field.type != sforce.fieldType.base64 && field.type != sforce.fieldType.boolean && field.type != sforce.fieldType.currency && field.type != sforce.fieldType.date && field.type != sforce.fieldType.datetime && field.type != sforce.fieldType.@double && field.type != sforce.fieldType.@int && field.type != sforce.fieldType.percent)
					{
						if (field.length != 0)
						{
							fNode = fieldsNode.Nodes.Add(field.name + " - " + field.type.ToString() + " (" + Convert.ToString(field.length) + ")");
						} 
						else 
						{
							fNode = fieldsNode.Nodes.Add(field.name + " (t:" + field.type.ToString() + ")");
						}
					}
					else 
					{
						fNode = fieldsNode.Nodes.Add(field.name + " (" + field.type.ToString() + ")");
					}
					fNode.ImageIndex = 3;
					fNode.SelectedImageIndex = 3;
					fNode.Tag = field;

					if (field.custom)
					{
						fNode.ForeColor = System.Drawing.Color.OliveDrab;
					}

					System.Windows.Forms.TreeNode aNode = fNode.Nodes.Add("Access");
					aNode.SelectedImageIndex = 4;
					aNode.ImageIndex = 4;
					RemoveCheckBox(aNode);

					System.Windows.Forms.TreeNode tempNode;
					if (field.nameField) 
					{
						tempNode = fNode.Nodes.Add(@"""name"" field");
						tempNode.NodeFont = new System.Drawing.Font("Verdana", 8, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
						tempNode.SelectedImageIndex = 4;
						tempNode.ImageIndex = 4;
					}

					if (field.createable)
					{
						tempNode = aNode.Nodes.Add("create-able");
						tempNode.NodeFont = new System.Drawing.Font("Verdana", 8, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
						tempNode.SelectedImageIndex = 16;
						tempNode.ImageIndex = 16;
						RemoveCheckBox(tempNode);
					}
					if (field.custom)
					{
						tempNode = aNode.Nodes.Add("custom");
						tempNode.SelectedImageIndex = 17;
						tempNode.ImageIndex = 17;
						RemoveCheckBox(tempNode);
					}
					
					if (field.filterable)
					{
						tempNode = aNode.Nodes.Add("filter-able");
						tempNode.NodeFont = new System.Drawing.Font("Verdana", 8, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
						tempNode.SelectedImageIndex = 20;
						tempNode.ImageIndex = 20;
						RemoveCheckBox(tempNode);
					}

					if (field.nillable)
					{
						tempNode = aNode.Nodes.Add("nillable");
						tempNode.NodeFont = new System.Drawing.Font("Verdana", 8, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
						tempNode.SelectedImageIndex = 21;
						tempNode.ImageIndex = 21;
						RemoveCheckBox(tempNode);
					}
					
					if (field.restrictedPicklist)
					{
						tempNode = aNode.Nodes.Add("restricted picklist");
						tempNode.NodeFont = new System.Drawing.Font("Verdana", 8, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
						tempNode.SelectedImageIndex = 4;
						tempNode.ImageIndex = 4;
						RemoveCheckBox(tempNode);
					}

					if (field.updateable)
					{
						tempNode = aNode.Nodes.Add("update-able");
						tempNode.NodeFont = new System.Drawing.Font("Verdana", 8, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
						tempNode.SelectedImageIndex = 28;
						tempNode.ImageIndex = 28;
						RemoveCheckBox(tempNode);
					}

					if (field.label.Length > 0)
					{
						System.Windows.Forms.TreeNode labelNode = fNode.Nodes.Add("label");
						RemoveCheckBox(labelNode.Nodes.Add(field.label));
						labelNode.SelectedImageIndex = 4;
						labelNode.ImageIndex = 4;
						RemoveCheckBox(labelNode);
					}
					
					System.Windows.Forms.TreeNode typeNode = fNode.Nodes.Add("type - " + field.type);
					typeNode.SelectedImageIndex = 4;
					typeNode.ImageIndex = 4;
					RemoveCheckBox(typeNode);

					if (field.length.ToString().Length > 0)
					{
						tempNode = typeNode.Nodes.Add("length: " + field.length);
						tempNode.SelectedImageIndex = 7;
						tempNode.ImageIndex = 7;
						RemoveCheckBox(tempNode);
					}

					if (field.byteLength.ToString().Length > 0)
					{
						tempNode = typeNode.Nodes.Add("byte-length: " + field.byteLength);
						tempNode.SelectedImageIndex = 7;
						tempNode.ImageIndex = 7;
						RemoveCheckBox(tempNode);
					}

					if (field.digits.ToString().Length > 0)
					{
						tempNode = typeNode.Nodes.Add("digits: " + field.digits);
						tempNode.SelectedImageIndex = 7;
						tempNode.ImageIndex = 7;
						RemoveCheckBox(tempNode);
					}

					if (field.precision.ToString().Length > 0)
					{
						tempNode = typeNode.Nodes.Add("precision: " + field.precision);
						tempNode.SelectedImageIndex = 7;
						tempNode.ImageIndex = 7;
						RemoveCheckBox(tempNode);
					}

					if (field.scale.ToString().Length > 0)
					{
						tempNode = typeNode.Nodes.Add("scale: " + field.scale);
						tempNode.SelectedImageIndex = 7;
						tempNode.ImageIndex = 7;
						RemoveCheckBox(tempNode);
					}

					if (field.picklistValues != null)
					{
						if (field.picklistValues[0] != null) 
						{
							System.Windows.Forms.TreeNode pNode = typeNode.Nodes.Add("Picklist Values");
							pNode.ImageIndex = 5;
							pNode.SelectedImageIndex = 5;
							RemoveCheckBox(pNode);
							for (int j=0;j<field.picklistValues.Length;j++)
							{
								sforce.PicklistEntry ple = field.picklistValues[j];
								tempNode = pNode.Nodes.Add(ple.value);
								tempNode.SelectedImageIndex = 6;
								tempNode.ImageIndex = 6;
								if (ple.label != null)
								{
									tempNode.Text += " - " + ple.label;
								}
								RemoveCheckBox(tempNode);
							}
						}
					}

					if (field.referenceTo != null)
					{
						if (field.referenceTo[0] != null)
						{
							System.Windows.Forms.TreeNode rNode = typeNode.Nodes.Add("Reference To");
							rNode.SelectedImageIndex = 5;
							rNode.ImageIndex = 5;
							RemoveCheckBox(rNode);
							for (int k=0;k<field.referenceTo.Length;k++)
							{
								tempNode = rNode.Nodes.Add(field.referenceTo[k]);
								tempNode.ImageIndex = 3;
								tempNode.SelectedImageIndex = 3;
								RemoveCheckBox(tempNode);
							}
						}
					}
				} 
				catch (Exception ex) 
				{
					System.Diagnostics.Trace.WriteLine(ex.Message);
				}
			}
		}
		
		private void AddAccessToTree(System.Windows.Forms.TreeNode AccessNode, sforce.DescribeSObjectResult describeResult, int IconIndex)
		{
			System.Windows.Forms.TreeNode tempNode = new TreeNode();
			if (describeResult.activateable)
			{
				tempNode = AccessNode.Nodes.Add("activate-able");
				tempNode.NodeFont = new System.Drawing.Font("Verdana", 8, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
				tempNode.SelectedImageIndex = 15;
				tempNode.ImageIndex = 15;
				RemoveCheckBox(tempNode);
			}
			
			if (describeResult.createable)
			{
				tempNode = AccessNode.Nodes.Add("create-able");
				tempNode.NodeFont = new System.Drawing.Font("Verdana", 8, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
				tempNode.SelectedImageIndex = 17;
				tempNode.ImageIndex = 17;
				RemoveCheckBox(tempNode);
			}
			
			if (describeResult.custom )
			{
				AccessNode.Parent.ForeColor = System.Drawing.Color.Olive;
				tempNode = AccessNode.Nodes.Add("custom");
				tempNode.NodeFont = new System.Drawing.Font("Verdana", 8, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
				tempNode.SelectedImageIndex = 17;
				tempNode.ImageIndex = 17;
				RemoveCheckBox(tempNode);
			}
			
			if (describeResult.deletable)
			{
				tempNode = AccessNode.Nodes.Add("delete-able");
				tempNode.NodeFont = new System.Drawing.Font("Verdana", 8, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
				tempNode.SelectedImageIndex = 19;
				tempNode.ImageIndex = 19;
				RemoveCheckBox(tempNode);
			}
			
			if (describeResult.queryable)
			{
				tempNode = AccessNode.Nodes.Add("query-able");
				tempNode.NodeFont = new System.Drawing.Font("Verdana", 8, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
				tempNode.SelectedImageIndex = 22;
				tempNode.ImageIndex = 22;
				RemoveCheckBox(tempNode);
			}
			
			if (describeResult.replicateable)
			{
				tempNode = AccessNode.Nodes.Add("replicate-able");
				tempNode.NodeFont = new System.Drawing.Font("Verdana", 8, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
				tempNode.SelectedImageIndex = 23;
				tempNode.ImageIndex = 23;
				RemoveCheckBox(tempNode);
			}
			
			if (describeResult.retrieveable)
			{
				tempNode = AccessNode.Nodes.Add("retrieve-able");
				tempNode.NodeFont = new System.Drawing.Font("Verdana", 8, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
				tempNode.SelectedImageIndex = 25;
				tempNode.ImageIndex = 25;
				RemoveCheckBox(tempNode);
			}
			
			if (describeResult.undeletable)
			{
				tempNode = AccessNode.Nodes.Add("undelete-able");
				tempNode.NodeFont = new System.Drawing.Font("Verdana", 8, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
				tempNode.SelectedImageIndex = 29;
				tempNode.ImageIndex = 29;
				RemoveCheckBox(tempNode);
			}
			
			if (describeResult.updateable)
			{
				tempNode = AccessNode.Nodes.Add("update-able");
				tempNode.NodeFont = new System.Drawing.Font("Verdana", 8, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
				tempNode.SelectedImageIndex = 28;
				tempNode.ImageIndex = 28;
				RemoveCheckBox(tempNode);
			}

			if (describeResult.searchable) 
			{
				tempNode = AccessNode.Nodes.Add("search-able");
				tempNode.NodeFont = new System.Drawing.Font("Verdana", 8, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
				tempNode.SelectedImageIndex = 28;
				tempNode.ImageIndex = 28;
				RemoveCheckBox(tempNode);
			}

			tempNode.Tag = "access";
		}

		private string GetNodeFieldName(System.Windows.Forms.TreeNode aNode) 
		{
			foreach (System.Windows.Forms.TreeNode n in aNode.Nodes) 
			{
				if (n.Text.ToLower() == "field")
					return n.Nodes[0].Text;
			}
			return null;
		}
		
		private void tvDesc_BeforeExpand(object sender, System.Windows.Forms.TreeViewCancelEventArgs e) 
		{
			if (e.Node.FirstNode.Text == "holder") 
			{
				AddEntityToTree(e.Node);
				CurrentRootNode = e.Node;
			}
		}

		private void tvDesc_DoubleClick(object sender, System.EventArgs e)
		{
			if (tvDesc.SelectedNode.Tag != null) 
			{
				bool isFieldNode = tvDesc.SelectedNode.Tag.GetType().Equals(typeof(sforce.Field));
				if (isFieldNode && FieldDoubleClicked != null)
					FieldDoubleClicked(tvDesc.SelectedNode, e);
			}
		}

		private void SetNodeChecks(TreeNode node) 
		{
			foreach (TreeNode n in node.Nodes) 
			{
				if (n.Tag != null) 
				{
					if (n.Tag.GetType() == typeof(sforce.Field) || n.Text.ToLower().Equals("fields") || n.Parent == null) 
					{
						n.Checked = node.Checked;
						if (n.Nodes.Count > 0) 
						{
							SetNodeChecks(n);
						}
					}
				}
			}
		}

		private string BuildSelectStatement(TreeNode node) 
		{
			string sel = "Select ";
			string list = "";
			string from;
			//go to the top of the tree
			if (node.Parent != null) 
			{
				while (node.Parent != null) 
				{
					node = node.Parent;
				}
			} 
			from = " " + node.Text;

			//now we go to the fields node, which is a child of the root
			TreeNode tn = null;
			foreach (TreeNode x in node.Nodes) 
			{
				if (x.Text == "Fields")
				{
					tn = x;
					break;
				}
			}

			//tn is the field node, get each checked field from the children
			foreach (TreeNode fld in tn.Nodes) 
			{
				if (fld.Checked) 
				{
					list += fld.Text.Substring(0, fld.Text.IndexOf(" ")).Trim() + ", ";
				}
			}

			if (list.Length == 0) 
			{
				return "";
			} 
			else 
			{
				//remove the last 2 charcters ", "
				list = list.Substring(0, list.Length - 2);
				//put it all together
				sel += list + " from " + from + " ";
				return sel;
			}
		}

		private SelectListChangedArguments BuildNodeSelectionArgs(TreeNode node) 
		{
			//go to the top of the tree
			if (node.Parent != null) 
			{
				while (node.Parent != null) 
				{
					node = node.Parent;
				}
			} 

			//now we go to the fields node, which is a child of the root
			TreeNode tn = null;
			foreach (TreeNode x in node.Nodes) 
			{
				if (x.Text == "Fields")
				{
					tn = x;
					break;
				}
			}

			//tn is the field node, get each checked field from the children
			ApiBrowserControl.SelectListChangedArguments slca = null;

			foreach (TreeNode fld in tn.Nodes) 
			{
				if (fld.Checked) 
				{
					if (slca == null) 
					{
						slca = new SelectListChangedArguments();
						slca.TableName = node.Text;
					}
					slca.AddField(fld.Text.Substring(0, fld.Text.IndexOf(" ")).Trim());
				}
			}
			return slca; 
		}

		public void SetItemChecked(string objectName, string fieldName) 
		{
			foreach(TreeNode tn in tvDesc.Nodes) 
			{
				if (tn.Text.ToLower().Equals(objectName.ToLower()))
				{
					if (tn.Nodes.Count == 1)
						AddEntityToTree(tn);

					foreach (TreeNode cn in tn.Nodes) 
					{
						if (cn.Text.ToLower().Equals("fields")) 
						{
							foreach (TreeNode fn in cn.Nodes) 
							{
								if (fn.Text.ToLower().StartsWith(fieldName.ToLower())) 
								{
									fn.Checked = true;
									return;
								}
							}
						}
					}
				}
			}
				
		}
		private void ClearAllChecks(TreeNode thisBranch)
		{
			foreach (TreeNode tn in tvDesc.Nodes) 
				if (tn.FirstNode.Text != "holder" && tn.Text != thisBranch.Text)
				{
					tn.Checked = false;
					SetNodeChecks(tn);
				}
		}

		private TreeNode GetNodeRoot(TreeNode tn) 
		{
			if (tn.Parent == null) 
			{
				return tn;
			} 
			else 
			{
				while (tn.Parent != null) 
				{
					tn = tn.Parent;
				}
				return tn;
			}
		}

		private void tvDesc_AfterCheck(object sender, TreeViewEventArgs e)
		{
			tvDesc.SelectedNode = e.Node;
			
			if (e.Node.FirstNode != null)
			{
				if (e.Node.FirstNode.Text == "holder") 
				{
					AddEntityToTree(e.Node);
				}
				bool checkVal = e.Node.Checked;
				tvDesc.AfterCheck -= new TreeViewEventHandler(tvDesc_AfterCheck);
				if (this.MultiObjectSelect.Equals(false)) 
				{
					ClearAllChecks(GetNodeRoot(e.Node));
				}
				e.Node.Checked = checkVal;
				if (e.Node.Checked && !this.GetNodeRoot(e.Node).Checked) this.GetNodeRoot(e.Node).Checked = true;
				tvDesc.AfterCheck +=new TreeViewEventHandler(tvDesc_AfterCheck);
				SetNodeChecks(e.Node);
				if (SelectListChanged != null) 
				{
					ArrayList args = null;
					foreach (TreeNode root in tvDesc.Nodes) 
					{
						if (root.Checked) 
						{
							if (args == null) args = new ArrayList();
							args.Add(BuildNodeSelectionArgs(root));
						}
					}
					try 
					{
						if (args == null)
							SelectListChanged(null, null);
						else if (args[0] != null)
							//SelectListChanged((ApiBrowserControl.SelectListChangedArguments[])args.ToArray(typeof(ApiBrowserControl.SelectListChangedArguments)), e);
							SelectListChanged(tvDesc, (SelectListChangedArguments[])args.ToArray(typeof(SelectListChangedArguments)));

						tvDesc.SelectedNode = e.Node;
					} 
					catch (Exception ex) 
					{
						System.Diagnostics.Trace.WriteLine(ex.Message);
					}
				}
			}
		}

		public sforce.DescribeSObjectResult CurrentObject 
		{
			get {return _currentObject; }
			set {_currentObject = value; }
		}

		public TreeNode CurrentRootNode
		{
			get {return _currentRootNode; }
			set {
				if (value == null) return;
				_currentRootNode = value; 
				this._currentObject = (sforce.DescribeSObjectResult)_currentRootNode.Tag; 
			}
		}

		private void tvDesc_BeforeSelect(object sender, TreeViewCancelEventArgs e)
		{
			if (this.GetNodeRoot(e.Node).Tag != null) 
			{
				this.CurrentRootNode = this.GetNodeRoot(e.Node);
			}
		}
		
		private static string  GetFieldLength(sforce.Field aNode, string fieldType )
		{
			int len = aNode.length;
			if (len  > 8000)
			{
				fieldType = "blob";
				return "16";
			} 
			else 
			{
				return len.ToString();
			}
		}


		private void tvDesc_BeforeCheck(object sender, TreeViewCancelEventArgs e)
		{
			if (!TreeViewExtender.HasCheckBox(e.Node)) 
			{ 
				e.Cancel = true; 
			} 
		}

		private int NodeLevel(string nodePath) 
		{
			return nodePath.Split(@"\".ToCharArray()).Length;
		}
		private void WriteNode(TreeNode tn) 
		{
			string tabs = "";
			for (int i=0;i<NodeLevel(tn.FullPath);i++)
				tabs += "\t";
			System.Diagnostics.Trace.WriteLine(tabs + tn.Text);
			//System.Diagnostics.Trace.WriteLine(tn.FullPath);
			foreach (TreeNode child in tn.Nodes) 
			{
				WriteNode(child);
			}
		}
		private void mnuDocObject_Click(object sender, System.EventArgs e)
		{
			TreeNode node = this.GetNodeRoot(this.tvDesc.SelectedNode);
			WriteNode(node);
		}

		private void ContextMenu1_Popup(object sender, System.EventArgs e)
		{
		
		}

		private TreeNode getFieldsNode(TreeNode node) 
		{
			System.Collections.IEnumerator ienum = node.Nodes.GetEnumerator();
			TreeNode n = null;
			while (ienum.MoveNext()) 
			{
				n = (TreeNode)ienum.Current;

				if (n.Tag != null && n.Tag.ToString().Equals("fields")) break;
			}
			return n;
		}

		private void muCreateTable_Click(object sender, System.EventArgs e)
		{
			if (tvDesc.SelectedNode.Parent == null) 
			{
				if (tvDesc.SelectedNode.FirstNode.Text.Equals("holder")) 
				{
					//Expand node
					bool cancel = false;
					System.Windows.Forms.TreeViewCancelEventArgs ea = new TreeViewCancelEventArgs(tvDesc.SelectedNode, cancel, System.Windows.Forms.TreeViewAction.Expand);
                    tvDesc_BeforeExpand(sender, ea);
				}
				//generate the schema
				bool onlySelected = System.Windows.Forms.MessageBox.Show("Do you want to limit the generation to just selected fields?", "Use Selected Fields", System.Windows.Forms.MessageBoxButtons.YesNo, System.Windows.Forms.MessageBoxIcon.Question).Equals(DialogResult.Yes);
				String tableName = tvDesc.SelectedNode.Text;
				TreeNode fields = this.getFieldsNode(tvDesc.SelectedNode);
				String output = "<complexType name=\"" + tableName + "\" parseto=\"bean\">";
				System.Collections.IEnumerator ienum = fields.Nodes.GetEnumerator();
				while (ienum.MoveNext()) 
				{
					TreeNode field = (TreeNode)ienum.Current;
					String fieldName = field.Text.Split("-".ToCharArray())[0].Trim();
					fieldName = fieldName.Split("(".ToCharArray())[0].Trim();
					if ((onlySelected && field.Checked) || (!onlySelected) || fieldName.ToLower().Equals("id"))
					{
						output += System.Environment.NewLine + "\t<element name=\"" + fieldName + "\" />";
					}
				}
				output += System.Environment.NewLine + "</complexType>";
				System.Diagnostics.Trace.WriteLine("\n\n" + output);
				new frmTextDisplay(output).ShowDialog();
			}
		}

		private void tvDesc_MouseDown(object sender, MouseEventArgs e)
		{
			if (e.Button.Equals(MouseButtons.Right)) 
			{
				tvDesc.SelectedNode = tvDesc.GetNodeAt(e.X, e.Y);
			}
		}
	}											  
}


